package UDP.Demo3;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.*;

/**

 * 基于UDP协议的聊天室客户端

 * 支持与服务器通信、发送消息和接收广播消息

 */

public class ChatClient {

    // 服务器端口号

    private static final int SERVER_PORT = 9876;

    // 服务器IP地址

    private static final String SERVER_IP = "localhost";

    // UDP套接字，用于发送和接收数据包

    private DatagramSocket socket;

    // 服务器地址

    private InetAddress serverAddress;

    // 客户端用户名

    private String username;

    /**

     * 构造函数，初始化客户端

     * @param username 客户端用户名

     */

    public ChatClient(String username) {

        try {

            this.username = username;

            // 创建UDP套接字（系统自动分配可用端口）

            socket = new DatagramSocket();

            // 获取服务器的IP地址对象

            serverAddress = InetAddress.getByName(SERVER_IP);

            // 发送上线消息给服务器

            sendMessage(username + " 上线了");

        } catch (SocketException | UnknownHostException e) {

            // 处理套接字创建失败或主机名解析失败的异常

            e.printStackTrace();

        }

    }

    /**

     * 启动客户端，开始接收和发送消息

     */

    public void start() {

        // 启动接收消息的线程（后台线程）

        Thread receiveThread = new Thread(() -> {

            // 创建接收数据的缓冲区

            byte[] buffer = new byte[1024];

            while (true) {

                try {

                    // 创建接收数据包对象

                    DatagramPacket receivePacket = new DatagramPacket(buffer, buffer.length);

                    // 接收服务器发送的数据包（阻塞方法）

                    socket.receive(receivePacket);

                    // 将接收到的字节数据转换为字符串并去除首尾空格

                    String message = new String(receivePacket.getData(), 0, receivePacket.getLength()).trim();

                    // 打印接收到的消息

                    System.out.println(message);

                } catch (IOException e) {

                    // 检查是否是因为套接字关闭导致的异常

                    if (socket.isClosed()) {

                        break; // 套接字已关闭，退出循环

                    }

                    e.printStackTrace();

                }

            }

        });

        // 设置为守护线程，主线程退出时自动终止

        receiveThread.setDaemon(true);

        // 启动线程

        receiveThread.start();

        // 主线程负责读取用户输入并发送消息

        try (BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))) {

            String message;

            // 循环读取用户输入（直到输入流结束）

            while ((message = reader.readLine()) != null) {

                // 用户输入"exit"时退出聊天

                if ("exit".equalsIgnoreCase(message)) {

                    // 发送下线消息给服务器

                    sendMessage(username + " 下线了");

                    // 关闭套接字

                    socket.close();

                    break;

                }

                // 发送用户输入的消息（格式：用户名: 消息内容）

                sendMessage(username + ": " + message);

            }

        } catch (IOException e) {

            // 处理输入输出异常

            e.printStackTrace();

        }

    }

    /**

     * 发送消息给服务器

     * @param message 要发送的消息内容

     */

    private void sendMessage(String message) {

        try {

            // 将消息转换为字节数组

            byte[] buffer = message.getBytes();

            // 创建要发送的数据包

            DatagramPacket packet = new DatagramPacket(

                    buffer,                 // 数据内容

                    buffer.length,          // 数据长度

                    serverAddress,          // 目标地址（服务器）

                    SERVER_PORT             // 目标端口（服务器）

            );

            // 发送数据包

            socket.send(packet);

        } catch (IOException e) {

            // 处理发送消息时的异常

            e.printStackTrace();

        }

    }

    /**

     * 程序入口点

     * @param args 命令行参数，必须包含用户名

     */

    public static void main(String[] args) {

        // 检查是否提供了用户名参数

        if (args.length != 1) {

            System.out.println("用法: java ChatClient <用户名>");

            return;

        }

        // 创建客户端实例

        ChatClient client = new ChatClient(args[0]);

        // 启动客户端

        client.start();

    }

}